/**
 * 协程安全socketAPI
 */
package impl

import (
	"errors"
	"sync"

	"github.com/gorilla/websocket"
)

var (
	data []byte
)

//设置api的链接类型
type Connection struct {
	WsConn    *websocket.Conn
	InChan    chan []byte
	OutChan   chan []byte
	closeChan chan byte
	mutex     sync.Mutex
	isClosed  bool
}

//初始化链接
/*
@params
	WsConn 	websocket链接
@return
	conn 	API链接信息
	err     错误信息
*/
func InitConnection(WsConn *websocket.Conn) (conn *Connection, err error) {
	conn = &Connection{
		WsConn: WsConn,
		InChan:    make(chan []byte, 1000),
		OutChan:   make(chan []byte, 1000),
		closeChan: make(chan byte, 1),
		isClosed:  false,
	}
	return
}

// 读取chan消息
/*
@params
	conn 	API链接信息
@return
	data 	消息
	err     错误信息
*/
func (conn *Connection) ReadMessage() (data []byte, err error) {

	select {
	case data = <-conn.InChan:
	case <-conn.closeChan:
		err = errors.New("connection is close")
	}
	return
}

// 发送消息放入chan
/*
@params
	conn 	API链接信息
@return
	data 	消息
	err     错误信息
*/
func (conn *Connection) WriteMessage(data []byte) (err error) {
	select {
	case conn.OutChan <- data:
	case <-conn.closeChan:
		err = errors.New("connection is close")
	}
	return
}

// 从socket中读取消息
func (conn *Connection) ReadLoop() {
	var (
		data []byte
		err  error
	)
	for {
		if _, data, err = conn.WsConn.ReadMessage(); err != nil {
			goto ERR
		}
		select {
		case conn.InChan <- data:
		case <-conn.closeChan:
			goto ERR
		}

	}
ERR:
	conn.Close()
}

//发送消息
func (conn *Connection) WriteLoop() {
	var (
		data []byte
		err  error
	)
	for {
		select {
		case data = <-conn.OutChan:
		case <-conn.closeChan:
			goto ERR
		}
		if err = conn.WsConn.WriteMessage(websocket.TextMessage, data); err != nil {
			goto ERR
		}
	}
ERR:
	conn.Close()
}

// 关闭websocket
func (conn *Connection) Close() {
	conn.WsConn.Close()
	conn.mutex.Lock()
	if !conn.isClosed {
		close(conn.closeChan)
		conn.isClosed = true
	}
	conn.mutex.Unlock()
}
